REM CallVob2Mkv.VBS
REM Author: Matthew Heaney
REM mailto:matthewjheaney@hotmail.com
REM
REM This script demonstrates how to call the VOB2MKV.EXE app from
REM a script.
REM
REM This particular script synthesizes the name of the output file
REM from the name of the directory that contains the VOB file(s).
REM 
REM It looks for the VOB file(s) in the folder named as the (only) argument,
REM or in the VIDEO_TS sub-folder if it exists.
REM 
REM The script captures the text sent to stdout by the app, parses
REM it using a regex, and then writes the value of the time to 
REM stdout from the script itself.  This is exactly what the app does.
REM
REM To run this script, you can specify it explicitly as an argument
REM to the cscript interpreter:
REM   cscript //nologo callvob2mkv.vbs <path to dvd folder>
REM
REM Alternatively, you can invoke the cscript interpreter implicitly.
REM First configure your environment to make cscript the default:
REM  cscript //H:cscript
REM This configuration only needs to be done once.  Now you can
REM run the script directly:
REM   callvob2mkv <path to dvd folder>
REM
REM This script is customized for the environment of my local
REM machine.  It's doubtful your environment is the same.  The
REM script is really intended to give you some ideas of what's
REM possible.  Change the script as necessary to adapt it to your
REM particular environment, and to satify your particular needs.

Option Explicit

Dim i, str  'scratch
Dim objArgs
Dim objFSO, objSrc, objTgt
Dim objShell, objExec, objStdOut
Dim strCmd, strLine
Dim reOut, mm

'We accept a single command-line argument, which is the path to
'the folder that contains the VOB file(s).

Set objArgs = Wscript.Arguments

If objArgs.Count <= 0 Then
   Wscript.Echo "too few arguments"
   Wscript.Quit
End If

If objArgs.Count > 1 Then
   Wscript.Echo "too many arguments"
   Wscript.Quit
End If

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("Wscript.Shell")

'Find the path to the VOB2KV app.
'First we assume the script is in the same folder as the app.

str = objFSO.GetParentFolderName(Wscript.ScriptFullName)
str = objFSO.BuildPath(str, "vob2mkv.exe")

If Not objFSO.FileExists(str) Then
   'Use the $(TargetPath) defined in the settings in 
   'Visual Studio for the VOB2MKV project.

   str = objShell.SpecialFolders("MyDocuments")

   If Not objFSO.FolderExists(str) Then
      Wscript.Echo "Documents folder not found"
      Wscript.Quit
   End If

   str = objFSO.BuildPath(str, "Visual Studio 2008")

   If Not objFSO.FolderExists(str) Then
      Wscript.Echo "Visual Studio 2008 folder not found"
      Wscript.Quit
   End If

   str = objFSO.BuildPath(str, "Projects")

   If Not objFSO.FolderExists(str) Then
      Wscript.Echo "Projects folder (in Visual Studio 2008) not found"
      Wscript.Quit
   End If

   str = objFSO.BuildPath(str, "bin")

   If Not objFSO.FolderExists(str) Then
      Wscript.Echo "bin folder (in Visual Studio 2008\Projects) not found"
      Wscript.Quit
   End If

   str = objFSO.BuildPath(str, "dvdutil_2008")

   If Not objFSO.FolderExists(str) Then
      Wscript.Echo "dvdutil folder (in Visual Studio 2008\Projects\bin) not found"
      Wscript.Quit
   End If

   str = objFSO.BuildPath(str, "vob2mkv_2008")

   If Not objFSO.FolderExists(str) Then
      Wscript.Echo "vob2mkv folder not found"
      Wscript.Quit
   End If

   str = objFSO.BuildPath(str, "Debug")

   If Not objFSO.FolderExists(str) Then
      Wscript.Echo "Debug folder (in vob2mkv) not found"
      Wscript.Quit
   End If

   str = objFSO.BuildPath(str, "vob2mkv.exe")

   If Not objFSO.FileExists(str) Then
      Wscript.Echo "vob2mkv.exe file not found"
      Wscript.Quit
   End If
End If

'We have found the path to the exe, so we use that to 
'form the command string, which we assemble incrementally.

strCmd = """" & str & """ --script-mode"  'exe

'Given the source folder root, we descend the folder hierarchy
'to find the VOB file(s).

REM Wscript.Echo "arg:", objArgs(0)
str = objArgs(0)

If Not objFSO.FolderExists(str) Then
   Wscript.Echo "Source folder not found"
   Wscript.Quit
End If

Set objSrc = objFSO.GetFolder(str)

'If this a DVD rip, then the root folder might
'have a child folder named "VIDEO_TS", so that folder
'exists, we assume the VOB files are there.

str = objFSO.BuildPath(objSrc.Path, "VIDEO_TS")

If Not objFSO.FolderExists(str) Then
   str = objSrc.Path
End If

'We have tenatively identified the folder containing
'the VOB files, so we now test for the existence of
'the first VOB file in the video title set.

'TODO: liberalize this name
str = objFSO.BuildPath(str, "VTS_01_1.VOB")

If Not objFSO.FileExists(str) Then
   Wscript.Echo "VTS_01_1.VOB file not found"
   Wscript.Quit
End If   

'We have confirmed the existence of the input file,
'so we append it to the command string.

strCmd = strCmd & " --input=""" & str & """"  'exe + input

'We next find the output file path.  We first locate the folder
'named "My Videos" (creating it if necessary) under "My Documents".

str = objShell.SpecialFolders("MyDocuments")

If Not objFSO.FolderExists(str) Then
   Wscript.Echo "Documents folder not found"
   Wscript.Quit
End If

Set objTgt = objFSO.GetFolder(str)

str = objFSO.BuildPath(objTgt.Path, "My Videos")

If objFSO.FolderExists(str) Then
   Set objTgt = objFSO.GetFolder(str)
Else
   Set objTgt = objFSO.CreateFolder(str)
End If

'We have the folder for the output file.  Next we name
'the output file based on the root directory specified as
'the argument to the script.

str = objFSO.BuildPath(objTgt.Path, objSrc.Name) & ".mkv"

'Finally we append the output file to the command string.

strCmd = strCmd & " --output=""" & str & """"

'For Debugging:
'strCmd = strCmd & " --list /V"

Wscript.Echo strCmd
Wscript.Echo

'We create a regex that matches the output of the app
'when it is run in script mode.

Set reOut = New RegExp
reOut.Pattern = "^TIME=(\S+)$"

'Finally we run the app, using the command line we assembled incrementally.

Set objExec = objShell.Exec(strCmd)
Set objStdOut = objExec.StdOut

'We use AtEndOfStream to terminate the loop.  The end of stream is
'reached when the app terminates, which is exactly what we want.

Do Until objStdOut.AtEndOfStream

   'Consume a line of output from the app:
   strLine = objStdOut.ReadLine

   'Parse the line using the regex we defined above:
   Set mm = reOut.Execute(strLine)

   If mm.Count <> 1 Then
      Wscript.StdOut.WriteLine
      Wscript.StdOut.WriteLine "ERROR: " & strLine
   Else
      'Write the time value to stdout.  This duplicates the behavior
      'of what the app would do, if it were run directly from the shell.
      Wscript.StdOut.Write vbCR
      Wscript.StdOut.Write mm(0).Submatches(0)

      'TODO: do something more interesting here?
      'One possibility is to use gui-based progress indicator
      'The nice thing about a progress indicator is that it can provide
      'a cancel button.  If we had a way to communicate with the app,
      'then we could terminate the app gracefully.
      'Alternatively, the progress indicator could be provided by the app
      'itself (under the control of another switch).
   End If

   'Does not appear to be necessary, if we're waiting for EOS on stdout:
   'If objExec.Status Then
   '   Exit Do
   'End If      
Loop

Wscript.StdOut.WriteLine

REM TODO: show progress using a window-based progress bar, instead of writing to std out
REM
REM Links to more scripting info
REM 
REM Script as drop target:
REM http://www.vistax64.com/powershell/52062-can-you-drag-n-drop-file-top-ps-script-run-script.html
REM
REM Special folders
REM MyDocuments, "My Documents"
REM http://www.wisesoft.co.uk/scripts/vbscript_display_special_folder_locations.aspx
REM objShell.SpecialFolders("MyDocuments")
REM http://en.wikipedia.org/wiki/Special_Folders
REM
REM http://www.activexperts.com/activmonitor/windowsmanagement/scripts/desktop/specialfolders/
REM
REM List Items in the My Documents Folder 
REM Reports the path to the My Documents folder, and then lists any items found in that folder.
REM For Windows NT 4.0 and Windows 98, this script requires Windows Script Host 5.1 and Internet
REM Explorer 4.0 or later. 
REM
REM Const MY_DOCUMENTS = &H5&
REM 
REM Set objShell = CreateObject("Shell.Application")
REM Set objFolder = objShell.Namespace(MY_DOCUMENTS)
REM Set objFolderItem = objFolder.Self
REM Wscript.Echo objFolderItem.Path
REM
REM Set colItems = objFolder.Items
REM For Each objItem in colItems
REM    Wscript.Echo objItem.Name
REM Next
REM
REM http://gallery.technet.microsoft.com/ScriptCenter/en-us/site/search?f%5B0%5D.Type=RootCategory&f%5B0%5D.Value=desktopmanagement&f%5B1%5D.Type=SubCategory&f%5B1%5D.Value=specialfolders
REM http://gallery.technet.microsoft.com/ScriptCenter/en-us/311c187e-cd33-4a23-aa55-cfb51fd61354
REM
REM Const MY_DOCUMENTS = &H5&
REM
REM Set objShell = CreateObject("Shell.Application")
REM Set objFolder = objShell.Namespace(MY_DOCUMENTS)
REM Set objFolderItem = objFolder.Self
REM Wscript.Echo objFolderItem.Path
REM 
REM Set colItems = objFolder.Items
REM For Each objItem in colItems
REM    Wscript.Echo objItem.Name
REM Next
REM
REM http://www.cruto.com/resources/vbscript/vbscript-examples/desktop/special/
REM http://msdn.microsoft.com/en-us/library/0ea7b5xe(VS.85).aspx